import or1200_definitions
import sys
sys.path.append("..")
import pyrtl
from  pyrtl import GPUSim

class Or1200Ctrl(object):
    def __init__(self):
        #I/O
        self.rst = pyrtl.Input(bitwidth=1, name='ctrl_rst')
        self.id_freeze = pyrtl.Input(bitwidth=1, name='ctrl_id_freeze')
        self.ex_freeze = pyrtl.Input(bitwidth=1, name='ctrl_ex_freezer')
        self.wb_freeze = pyrtl.Input(bitwidth=1, name='ctrl_wb_freeze')
        self.flushpipe = pyrtl.Input(bitwidth=1, name='ctrl_flushpipe')
        self.if_insn = pyrtl.Input(bitwidth=32, name='ctrl_if_insn')
        self.branch_taken = pyrtl.Input(bitwidth=1, name='ctrl_branch_taken')
        self.wbforw_valid = pyrtl.Input(bitwidth=1, name='ctrl_wbforw_valid')
        self.du_hwbkpt = pyrtl.Input(bitwidth=1, name='ctrl_du_hwbkpt')
        # Internal wires and regs

        self.id_void = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.ex_insn = pyrtl.WireVector(bitwidth=32) #, name='ex_insn')
        self.branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH) #, name='branch_op')
        # self.ex_insn_out = pyrtl.Output(bitwidth=32)  # , name='ex_insn')
        # self.branch_o_outp = pyrtl.Output(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)  # , name='branch_op')

        self.wb_rfaddrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        self.sel_imm = pyrtl.WireVector(bitwidth=1)
        self.imm_signextend = pyrtl.WireVector(bitwidth=1)
        self.rf_addrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH) #, name='rf_addrw')
        self.pre_branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)

        #self.rf_addrw_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH, name='rf_addrw')
        self.rf_addra = pyrtl.Output(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH, name='rf_addra')
        self.rf_addrb = pyrtl.Output(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH, name='rf_addrb')
        self.rf_rda = pyrtl.Output(bitwidth=1, name='rf_rda')
        self.rf_rdb = pyrtl.Output(bitwidth=1, name='rf_rdb')
        self.comp_op = pyrtl.Output(bitwidth=or1200_definitions.OR1200_COMPOP_WIDTH, name='comp_op')
        self.alu_op = pyrtl.Output(bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH, name='alu_op')
        self.shrot_op = pyrtl.Output(bitwidth=or1200_definitions.OR1200_SHROTOP_WIDTH, name='shrot_op')
        self.rfwb_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH, name='rfwb_op')
        #self.rfwb_op_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH, name='rfwb_op')

        self.wb_insn = pyrtl.Output(bitwidth=32, name='wb_insn')
        self.simm = pyrtl.Output(bitwidth=32, name='simm')
        self.branch_addrofs = pyrtl.Output(bitwidth=30, name='branch_addrofs')
        self.lsu_addrofs = pyrtl.Output(bitwidth=32, name='lsu_addrofs')
        self.sel_a = pyrtl.Output(bitwidth=or1200_definitions.OR1200_SEL_WIDTH, name='sel_a')
        self.sel_b = pyrtl.Output(bitwidth=or1200_definitions.OR1200_SEL_WIDTH, name='sel_b')
        self.lsu_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH, name='lsu_op')
        #self.lsu_op_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH, name='lsu_op')

        self.multicycle = pyrtl.Output(bitwidth=or1200_definitions.OR1200_MULTICYCLE_WIDTH, name='multicycle')
        self.spr_addrimm = pyrtl.Output(bitwidth=16, name='spr_addrimm')
        self.sig_syscall = pyrtl.Output(bitwidth=1, name='sig_syscall')
        self.sig_trap = pyrtl.Output(bitwidth=1, name='sig_trap')
        self.force_dslot_fetch = pyrtl.Output(bitwidth=1, name='force_dslot_fetch')

        self.no_more_dslot = pyrtl.Output(bitwidth=1,name='self.no_more_dslot')
        self.ex_void = pyrtl.Output(bitwidth=1, name='ex_void')
        self.rfe = pyrtl.Output(bitwidth=1, name='rfe')
        self.except_illegal = pyrtl.Output(bitwidth=1, name='except_illegal')

        self.ex_insn_out = pyrtl.Output(bitwidth=32, name='ctrl_ex_insn')
        self.branch_op_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH, name='ctrl_branch_op')
        self.rf_addrw_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH,
                                             name='ctrl_rf_addrw')
        self.rfwb_op_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH, name='ctrl_rfwb_op')
        self.lsu_op_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH, name='ctrl_lsu_op')

        self.branch_op_out <<= self.branch_op
        self.ex_insn_out <<= self.ex_insn
        self.rf_addrw_out <<= self.rf_addrw
        self.rfwb_op_out <<= self.rfwb_op
        self.lsu_op_out <<= self.lsu_op
        
        #initialize all the parts
        generatSela = GeneratSela()
        generatSelb = GeneratSelb()
        decodespr = DecodeSpr()
        decodemul = DecodeMul()
        decodeimm = DecodeImm()
        lsuaddroffset = LsuAddrOffset()
        writeaddr = WriteAddr()
        rfinwb = RfInWb()
        insninid = InsnInId()
        insninex = InsnInEx()
        insninwb = InsnInWb()
        decodeselimm = DecodeSelimm()
        decodeexcept = DecodeExcept()
        decodeofaluop = DecodeOfAluop()
        decodeofshrotop = DecodeOfShrotop()
        decodeofrfwbop = DecodeOfRfwbop()
        decodeofpre = DecodeOfPre()
        generatofbranch = GeneratOfBranch()
        decodeoflsuop = DecodeOfLsuop()
        decodeofcompop = DecodeOfCompop()
        decodeoflsys = DecodeOfLsys()
        decodeofltrap = DecodeOfLtrap()
        
        self.sel_a <<= generatSela.sel_a
        generatSela.rf_addrw <<= self.rf_addrw
        generatSela.id_insn <<= self.id_insn
        generatSela.rfwb_op <<= self.rfwb_op
        generatSela.wbforw_valid <<= self.wbforw_valid
        generatSela.wb_rfaddrw <<= self.wb_rfaddrw
        self.sel_b <<= generatSelb.sel_b
        generatSelb.rf_addrw <<= self.rf_addrw
        generatSelb.sel_imm <<= self.sel_imm
        generatSelb.id_insn <<= self.id_insn
        generatSelb.rfwb_op <<= self.rfwb_op
        generatSelb.wbforw_valid <<= self.wbforw_valid
        generatSelb.wb_rfaddrw <<= self.wb_rfaddrw
        decodespr.rst <<= self.rst
        self.spr_addrimm <<= decodespr.spr_addrimm
        decodespr.ex_freeze <<= self.ex_freeze
        decodespr.id_freeze <<= self.id_freeze
        decodespr.flushpipe <<= self.flushpipe
        decodespr.id_insn <<= self.id_insn
        decodemul.id_insn <<= self.id_insn
        self.multicycle <<= decodemul.multicycle
        decodeimm.id_insn <<= self.id_insn
        self.imm_signextend <<= decodeimm.imm_signextend
        lsuaddroffset.lsu_op <<= self.lsu_op
        lsuaddroffset.ex_insn <<= self.ex_insn
        self.lsu_addrofs <<= lsuaddroffset.lsu_addrofs
        writeaddr.rst <<= self.rst
        self.rf_addrw <<= writeaddr.rf_addrw
        writeaddr.ex_freeze <<= self.ex_freeze
        writeaddr.id_freeze <<= self.id_freeze
        writeaddr.pre_branch_op <<= self.pre_branch_op
        writeaddr.id_insn <<= self.id_insn
        rfinwb.rst <<= self.rst
        self.wb_rfaddrw <<= rfinwb.wb_rfaddrw
        rfinwb.rf_addrw <<= self.rf_addrw
        rfinwb.wb_freeze <<= self.wb_freeze
        insninid.rst <<= self.rst
        self.id_insn <<= insninid.id_insn
        insninid.flushpipe <<= self.flushpipe
        insninid.id_freeze <<= self.id_freeze
        insninid.if_insn <<= self.if_insn
        insninex.rst <<= self.rst
        self.ex_insn <<= insninex.ex_insn
        insninex.ex_freeze <<= self.ex_freeze
        insninex.id_freeze <<= self.id_freeze
        insninex.flushpipe <<= self.flushpipe
        insninex.id_insn <<= self.id_insn
        insninwb.rst <<= self.rst
        self.wb_insn <<= insninwb.wb_insn
        insninwb.ex_insn <<= self.ex_insn
        insninwb.flushpipe <<= self.flushpipe
        insninwb.wb_freeze <<= self.wb_freeze
        decodeselimm.rst <<= self.rst
        self.sel_imm <<= decodeselimm.sel_imm
        decodeselimm.id_freeze <<= self.id_freeze
        decodeselimm.if_insn <<= self.if_insn
        decodeexcept.rst <<= self.rst
        self.except_illegal <<= decodeexcept.except_illegal
        decodeexcept.ex_freeze <<= self.ex_freeze
        decodeexcept.id_freeze <<= self.id_freeze
        decodeexcept.flushpipe <<= self.flushpipe
        decodeexcept.id_insn <<= self.id_insn
        decodeofaluop.rst <<= self.rst
        self.alu_op <<= decodeofaluop.alu_op
        decodeofaluop.ex_freeze <<= self.ex_freeze
        decodeofaluop.id_freeze <<= self.id_freeze
        decodeofaluop.flushpipe <<= self.flushpipe
        decodeofaluop.id_insn <<= self.id_insn
        decodeofshrotop.rst <<= self.rst
        self.shrot_op <<= decodeofshrotop.shrot_op
        decodeofshrotop.ex_freeze <<= self.ex_freeze
        decodeofshrotop.id_freeze <<= self.id_freeze
        decodeofshrotop.flushpipe <<= self.flushpipe
        decodeofshrotop.id_insn <<= self.id_insn
        decodeofrfwbop.rst <<= self.rst
        self.rfwb_op <<= decodeofrfwbop.rfwb_op
        decodeofrfwbop.ex_freeze <<= self.ex_freeze
        decodeofrfwbop.id_freeze <<= self.id_freeze
        decodeofrfwbop.flushpipe <<= self.flushpipe
        decodeofrfwbop.id_insn <<= self.id_insn
        decodeofpre.rst <<= self.rst
        self.pre_branch_op <<= decodeofpre.pre_branch_op
        decodeofpre.id_freeze <<= self.id_freeze
        decodeofpre.flushpipe <<= self.flushpipe
        decodeofpre.if_insn <<= self.if_insn
        generatofbranch.rst <<= self.rst
        self.branch_op <<= generatofbranch.branch_op
        generatofbranch.ex_freeze <<= self.ex_freeze
        generatofbranch.id_freeze <<= self.id_freeze
        generatofbranch.flushpipe <<= self.flushpipe
        generatofbranch.pre_branch_op <<= self.pre_branch_op
        decodeoflsuop.rst <<= self.rst
        self.lsu_op <<= decodeoflsuop.lsu_op
        decodeoflsuop.ex_freeze <<= self.ex_freeze
        decodeoflsuop.id_freeze <<= self.id_freeze
        decodeoflsuop.flushpipe <<= self.flushpipe
        decodeoflsuop.id_insn <<= self.id_insn
        decodeofcompop.rst <<= self.rst
        self.comp_op <<= decodeofcompop.comp_op
        decodeofcompop.ex_freeze <<= self.ex_freeze
        decodeofcompop.id_freeze <<= self.id_freeze
        decodeofcompop.flushpipe <<= self.flushpipe
        decodeofcompop.id_insn <<= self.id_insn
        decodeoflsys.rst <<= self.rst
        self.sig_syscall <<= decodeoflsys.sig_syscall
        decodeoflsys.ex_freeze <<= self.ex_freeze
        decodeoflsys.id_freeze <<= self.id_freeze
        decodeoflsys.flushpipe <<= self.flushpipe
        decodeoflsys.id_insn <<= self.id_insn
        decodeofltrap.rst <<= self.rst
        self.sig_trap <<= decodeofltrap.sig_trap
        decodeofltrap.ex_freeze <<= self.ex_freeze
        decodeofltrap.id_freeze <<= self.id_freeze
        decodeofltrap.flushpipe <<= self.flushpipe
        decodeofltrap.id_insn <<= self.id_insn
        decodeofltrap.du_hwbkpt <<= self.du_hwbkpt
        
        #Register file read addresses
        self.rf_addra <<= self.if_insn[16:21]
        self.rf_addrb <<= self.if_insn[11:16]
        self.rf_rda <<= self.if_insn[31]
        self.rf_rdb <<= self.if_insn[30]
    
        #Force fetch of delay slot instruction when jump/branch is #preceeded by load/store
        #instructions
        #SIMON
        self.force_dslot_fetch <<= pyrtl.Const(0b0, bitwidth=1)
        self.no_more_dslot <<= or1200_definitions.Or(self.branch_op) & (~self.id_void) & self.branch_taken | (self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE)
        self.id_void <<= (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_NOP) & self.id_insn[16]
        self.ex_void <<= (self.ex_insn[26:32] == or1200_definitions.OR1200_OR32_NOP) & self.ex_insn[16]
        
        #Sign/Zero extension of immediates
        self.simm <<= pyrtl.mux((self.imm_signextend == or1200_definitions.ONE), self.id_insn[0:16].zero_extended(32), self.id_insn[0:16].sign_extended(32))
        
        #Sign extension of branch offset
        self.branch_addrofs <<= self.ex_insn[0:26].sign_extended(30)
        self.rfe <<= (self.pre_branch_op == or1200_definitions.OR1200_BRANCHOP_RFE) | (self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE)


class Or1200Ctrl_wire(object):
    def __init__(self):
        # I/O
        self.rst = pyrtl.WireVector(bitwidth=1, name='ctrl_rst')
        self.id_freeze = pyrtl.WireVector(bitwidth=1, name='ctrl_id_freeze')
        self.ex_freeze = pyrtl.WireVector(bitwidth=1, name='ctrl_ex_freezer')
        self.wb_freeze = pyrtl.WireVector(bitwidth=1, name='ctrl_wb_freeze')
        self.flushpipe = pyrtl.WireVector(bitwidth=1, name='ctrl_flushpipe')
        self.if_insn = pyrtl.WireVector(bitwidth=32, name='ctrl_if_insn')
        self.branch_taken = pyrtl.WireVector(bitwidth=1, name='ctrl_branch_taken')
        self.wbforw_valid = pyrtl.WireVector(bitwidth=1, name='ctrl_wbforw_valid')
        self.du_hwbkpt = pyrtl.WireVector(bitwidth=1, name='ctrl_du_hwbkpt')
        # Internal wires and regs

        self.id_void = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.ex_insn = pyrtl.WireVector(bitwidth=32)  # , name='ex_insn')
        self.branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)  # , name='branch_op')
        # self.ex_insn_out = pyrtl.WireVector(bitwidth=32)  # , name='ex_insn')
        # self.branch_o_outp = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)  # , name='branch_op')

        self.wb_rfaddrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        self.sel_imm = pyrtl.WireVector(bitwidth=1)
        self.imm_signextend = pyrtl.WireVector(bitwidth=1)
        self.rf_addrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)  # , name='rf_addrw')
        self.pre_branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)

        # self.rf_addrw_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH, name='rf_addrw')
        self.rf_addra = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH, name='rf_addra')
        self.rf_addrb = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH, name='rf_addrb')
        self.rf_rda = pyrtl.WireVector(bitwidth=1, name='rf_rda')
        self.rf_rdb = pyrtl.WireVector(bitwidth=1, name='rf_rdb')
        self.comp_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_COMPOP_WIDTH, name='comp_op')
        self.alu_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH, name='alu_op')
        self.shrot_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SHROTOP_WIDTH, name='shrot_op')
        self.rfwb_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH, name='rfwb_op')
        # self.rfwb_op_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH, name='rfwb_op')

        self.wb_insn = pyrtl.WireVector(bitwidth=32, name='wb_insn')
        self.simm = pyrtl.WireVector(bitwidth=32, name='simm')
        self.branch_addrofs = pyrtl.WireVector(bitwidth=30, name='branch_addrofs')
        self.lsu_addrofs = pyrtl.WireVector(bitwidth=32, name='lsu_addrofs')
        self.sel_a = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SEL_WIDTH, name='sel_a')
        self.sel_b = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SEL_WIDTH, name='sel_b')
        self.lsu_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH, name='lsu_op')
        # self.lsu_op_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH, name='lsu_op')

        self.multicycle = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_MULTICYCLE_WIDTH, name='multicycle')
        self.spr_addrimm = pyrtl.WireVector(bitwidth=16, name='spr_addrimm')
        self.sig_syscall = pyrtl.WireVector(bitwidth=1, name='sig_syscall')
        self.sig_trap = pyrtl.WireVector(bitwidth=1, name='sig_trap')
        self.force_dslot_fetch = pyrtl.WireVector(bitwidth=1, name='force_dslot_fetch')

        self.no_more_dslot = pyrtl.WireVector(bitwidth=1, name='self.no_more_dslot')
        self.ex_void = pyrtl.WireVector(bitwidth=1, name='ex_void')
        self.rfe = pyrtl.WireVector(bitwidth=1, name='rfe')
        self.except_illegal = pyrtl.WireVector(bitwidth=1, name='except_illegal')

        self.ex_insn_out = pyrtl.WireVector(bitwidth=32, name='ctrl_ex_insn')
        self.branch_op_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH, name='ctrl_branch_op')
        self.rf_addrw_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH,
                                             name='ctrl_rf_addrw')
        self.rfwb_op_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH, name='ctrl_rfwb_op')
        self.lsu_op_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH, name='ctrl_lsu_op')

        self.branch_op_out <<= self.branch_op
        self.ex_insn_out<<=self.ex_insn
        self.rf_addrw_out<<=self.rf_addrw
        self.rfwb_op_out<<=self.rfwb_op
        self.lsu_op_out<<=self.lsu_op

        # initialize all the parts
        generatSela = GeneratSela()
        generatSelb = GeneratSelb()
        decodespr = DecodeSpr()
        decodemul = DecodeMul()
        decodeimm = DecodeImm()
        lsuaddroffset = LsuAddrOffset()
        writeaddr = WriteAddr()
        rfinwb = RfInWb()
        insninid = InsnInId()
        insninex = InsnInEx()
        insninwb = InsnInWb()
        decodeselimm = DecodeSelimm()
        decodeexcept = DecodeExcept()
        decodeofaluop = DecodeOfAluop()
        decodeofshrotop = DecodeOfShrotop()
        decodeofrfwbop = DecodeOfRfwbop()
        decodeofpre = DecodeOfPre()
        generatofbranch = GeneratOfBranch()
        decodeoflsuop = DecodeOfLsuop()
        decodeofcompop = DecodeOfCompop()
        decodeoflsys = DecodeOfLsys()
        decodeofltrap = DecodeOfLtrap()

        self.sel_a <<= generatSela.sel_a
        generatSela.rf_addrw <<= self.rf_addrw
        generatSela.id_insn <<= self.id_insn
        generatSela.rfwb_op <<= self.rfwb_op
        generatSela.wbforw_valid <<= self.wbforw_valid
        generatSela.wb_rfaddrw <<= self.wb_rfaddrw
        self.sel_b <<= generatSelb.sel_b
        generatSelb.rf_addrw <<= self.rf_addrw
        generatSelb.sel_imm <<= self.sel_imm
        generatSelb.id_insn <<= self.id_insn
        generatSelb.rfwb_op <<= self.rfwb_op
        generatSelb.wbforw_valid <<= self.wbforw_valid
        generatSelb.wb_rfaddrw <<= self.wb_rfaddrw
        decodespr.rst <<= self.rst
        self.spr_addrimm <<= decodespr.spr_addrimm
        decodespr.ex_freeze <<= self.ex_freeze
        decodespr.id_freeze <<= self.id_freeze
        decodespr.flushpipe <<= self.flushpipe
        decodespr.id_insn <<= self.id_insn
        decodemul.id_insn <<= self.id_insn
        self.multicycle <<= decodemul.multicycle
        decodeimm.id_insn <<= self.id_insn
        self.imm_signextend <<= decodeimm.imm_signextend
        lsuaddroffset.lsu_op <<= self.lsu_op
        lsuaddroffset.ex_insn <<= self.ex_insn
        self.lsu_addrofs <<= lsuaddroffset.lsu_addrofs
        writeaddr.rst <<= self.rst
        self.rf_addrw <<= writeaddr.rf_addrw
        writeaddr.ex_freeze <<= self.ex_freeze
        writeaddr.id_freeze <<= self.id_freeze
        writeaddr.pre_branch_op <<= self.pre_branch_op
        writeaddr.id_insn <<= self.id_insn
        rfinwb.rst <<= self.rst
        self.wb_rfaddrw <<= rfinwb.wb_rfaddrw
        rfinwb.rf_addrw <<= self.rf_addrw
        rfinwb.wb_freeze <<= self.wb_freeze
        insninid.rst <<= self.rst
        self.id_insn <<= insninid.id_insn
        insninid.flushpipe <<= self.flushpipe
        insninid.id_freeze <<= self.id_freeze
        insninid.if_insn <<= self.if_insn
        insninex.rst <<= self.rst
        self.ex_insn <<= insninex.ex_insn
        insninex.ex_freeze <<= self.ex_freeze
        insninex.id_freeze <<= self.id_freeze
        insninex.flushpipe <<= self.flushpipe
        insninex.id_insn <<= self.id_insn
        insninwb.rst <<= self.rst
        self.wb_insn <<= insninwb.wb_insn
        insninwb.ex_insn <<= self.ex_insn
        insninwb.flushpipe <<= self.flushpipe
        insninwb.wb_freeze <<= self.wb_freeze
        decodeselimm.rst <<= self.rst
        self.sel_imm <<= decodeselimm.sel_imm
        decodeselimm.id_freeze <<= self.id_freeze
        decodeselimm.if_insn <<= self.if_insn
        decodeexcept.rst <<= self.rst
        self.except_illegal <<= decodeexcept.except_illegal
        decodeexcept.ex_freeze <<= self.ex_freeze
        decodeexcept.id_freeze <<= self.id_freeze
        decodeexcept.flushpipe <<= self.flushpipe
        decodeexcept.id_insn <<= self.id_insn
        decodeofaluop.rst <<= self.rst
        self.alu_op <<= decodeofaluop.alu_op
        decodeofaluop.ex_freeze <<= self.ex_freeze
        decodeofaluop.id_freeze <<= self.id_freeze
        decodeofaluop.flushpipe <<= self.flushpipe
        decodeofaluop.id_insn <<= self.id_insn
        decodeofshrotop.rst <<= self.rst
        self.shrot_op <<= decodeofshrotop.shrot_op
        decodeofshrotop.ex_freeze <<= self.ex_freeze
        decodeofshrotop.id_freeze <<= self.id_freeze
        decodeofshrotop.flushpipe <<= self.flushpipe
        decodeofshrotop.id_insn <<= self.id_insn
        decodeofrfwbop.rst <<= self.rst
        self.rfwb_op <<= decodeofrfwbop.rfwb_op
        decodeofrfwbop.ex_freeze <<= self.ex_freeze
        decodeofrfwbop.id_freeze <<= self.id_freeze
        decodeofrfwbop.flushpipe <<= self.flushpipe
        decodeofrfwbop.id_insn <<= self.id_insn
        decodeofpre.rst <<= self.rst
        self.pre_branch_op <<= decodeofpre.pre_branch_op
        decodeofpre.id_freeze <<= self.id_freeze
        decodeofpre.flushpipe <<= self.flushpipe
        decodeofpre.if_insn <<= self.if_insn
        generatofbranch.rst <<= self.rst
        self.branch_op <<= generatofbranch.branch_op
        generatofbranch.ex_freeze <<= self.ex_freeze
        generatofbranch.id_freeze <<= self.id_freeze
        generatofbranch.flushpipe <<= self.flushpipe
        generatofbranch.pre_branch_op <<= self.pre_branch_op
        decodeoflsuop.rst <<= self.rst
        self.lsu_op <<= decodeoflsuop.lsu_op
        decodeoflsuop.ex_freeze <<= self.ex_freeze
        decodeoflsuop.id_freeze <<= self.id_freeze
        decodeoflsuop.flushpipe <<= self.flushpipe
        decodeoflsuop.id_insn <<= self.id_insn
        decodeofcompop.rst <<= self.rst
        self.comp_op <<= decodeofcompop.comp_op
        decodeofcompop.ex_freeze <<= self.ex_freeze
        decodeofcompop.id_freeze <<= self.id_freeze
        decodeofcompop.flushpipe <<= self.flushpipe
        decodeofcompop.id_insn <<= self.id_insn
        decodeoflsys.rst <<= self.rst
        self.sig_syscall <<= decodeoflsys.sig_syscall
        decodeoflsys.ex_freeze <<= self.ex_freeze
        decodeoflsys.id_freeze <<= self.id_freeze
        decodeoflsys.flushpipe <<= self.flushpipe
        decodeoflsys.id_insn <<= self.id_insn
        decodeofltrap.rst <<= self.rst
        self.sig_trap <<= decodeofltrap.sig_trap
        decodeofltrap.ex_freeze <<= self.ex_freeze
        decodeofltrap.id_freeze <<= self.id_freeze
        decodeofltrap.flushpipe <<= self.flushpipe
        decodeofltrap.id_insn <<= self.id_insn
        decodeofltrap.du_hwbkpt <<= self.du_hwbkpt

        # Register file read addresses
        self.rf_addra <<= self.if_insn[16:21]
        self.rf_addrb <<= self.if_insn[11:16]
        self.rf_rda <<= self.if_insn[31]
        self.rf_rdb <<= self.if_insn[30]

        # Force fetch of delay slot instruction when jump/branch is #preceeded by load/store
        # instructions
        # SIMON
        self.force_dslot_fetch <<= pyrtl.Const(0b0, bitwidth=1)
        self.no_more_dslot <<= or1200_definitions.Or(self.branch_op) & (~self.id_void) & self.branch_taken | (
                    self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE)
        self.id_void <<= (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_NOP) & self.id_insn[16]
        self.ex_void <<= (self.ex_insn[26:32] == or1200_definitions.OR1200_OR32_NOP) & self.ex_insn[16]

        # Sign/Zero extension of immediates
        self.simm <<= pyrtl.mux((self.imm_signextend == or1200_definitions.ONE), self.id_insn[0:16].zero_extended(32),
                                self.id_insn[0:16].sign_extended(32))

        # Sign extension of branch offset
        self.branch_addrofs <<= self.ex_insn[0:26].sign_extended(30)
        self.rfe <<= (self.pre_branch_op == or1200_definitions.OR1200_BRANCHOP_RFE) | (
                    self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE)


#Generation of sel_a
class GeneratSela(object):
    def __init__(self):
        self.sel_a = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SEL_WIDTH)
        self.rf_addrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.rfwb_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH)
        self.wbforw_valid = pyrtl.WireVector(bitwidth=1)
        self.wb_rfaddrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        
        with pyrtl.conditional_assignment:
            with (self.id_insn[16:21] == self.rf_addrw) & (self.rfwb_op[0] == or1200_definitions.ONE):
                self.sel_a |= or1200_definitions.OR1200_SEL_EX_FORW
            with (self.id_insn[16:21] == self.wb_rfaddrw) & (self.wbforw_valid == or1200_definitions.ONE):
                self.sel_a |= or1200_definitions.OR1200_SEL_WB_FORW
            with pyrtl.otherwise:
                self.sel_a |= or1200_definitions.OR1200_SEL_RF
                
#Generation of sel_b
class GeneratSelb(object):
    def __init__(self):
        self.sel_b = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SEL_WIDTH)
        self.rf_addrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        self.sel_imm = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.rfwb_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH)
        self.wbforw_valid = pyrtl.WireVector(bitwidth=1)
        self.wb_rfaddrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        
        with pyrtl.conditional_assignment:
            with self.sel_imm == or1200_definitions.ONE:
                self.sel_b |= or1200_definitions.OR1200_SEL_IMM
            with (self.id_insn[11:16] == self.rf_addrw) & (self.rfwb_op[0] == or1200_definitions.ONE):
                self.sel_b |= or1200_definitions.OR1200_SEL_EX_FORW
            with (self.id_insn[11:16] == self.wb_rfaddrw) & (self.wbforw_valid == or1200_definitions.ONE):
                self.sel_b |= or1200_definitions.OR1200_SEL_WB_FORW
            with pyrtl.otherwise:
                self.sel_b |= or1200_definitions.OR1200_SEL_RF
                
#Decode of spr_addrimm
class DecodeSpr(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.spr_addrimm = pyrtl.WireVector(bitwidth=16)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.spr_addrimm |= pyrtl.Const(0x0, bitwidth=16)
            with (~self.ex_freeze & self.id_freeze |self.flushpipe) == or1200_definitions.ONE:
                self.spr_addrimm |= pyrtl.Const(0x0, bitwidth=16)
            with ~self.ex_freeze == or1200_definitions.ONE:
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MFSPR:
                    self.spr_addrimm |= self.id_insn[0:16]
                with pyrtl.otherwise:
                    self.spr_addrimm |= pyrtl.concat(self.id_insn[21:26], self.id_insn[0:11])
                    
#Decode of multicycle
class DecodeMul(object):
    def __init__(self):
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.multicycle = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_MULTICYCLE_WIDTH)
        
        with pyrtl.conditional_assignment:
            with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ALU:
                self.multicycle |= self.id_insn[or1200_definitions.OR1200_ALUMCYC_POS]
            with pyrtl.otherwise:
                self.multicycle |= or1200_definitions.OR1200_ONE_CYCLE
                
#Decode of imm_signextend
class DecodeImm(object):
    def __init__(self):
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.imm_signextend = pyrtl.WireVector(bitwidth=1)
        
        with pyrtl.conditional_assignment:
            with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDI:
                self.imm_signextend |= pyrtl.Const(0b1, bitwidth=1)
            with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDIC:
                self.imm_signextend |= pyrtl.Const(0b1, bitwidth=1)
            with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_XORI:
                self.imm_signextend |= pyrtl.Const(0b1, bitwidth=1)
            with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SFXXI:
                self.imm_signextend |= pyrtl.Const(0b1, bitwidth=1)
            with pyrtl.otherwise:
                self.imm_signextend |= pyrtl.Const(0b0, bitwidth=1)
         
#LSU addr offset
class LsuAddrOffset(object):
    def __init__(self):
        self.lsu_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH)
        self.ex_insn = pyrtl.WireVector(bitwidth=32)
        self.lsu_addrofs = pyrtl.WireVector(bitwidth=32)
        
        #self.lsu_addrofs[0:11] <<= self.ex_insn[0:11]
        #lsu_addrofs = [i for i in self.lsu_addrofs]
        
        #self.lsu_addrofs <<= pyrtl.concat(*reversed(lsu_addrofs))
        with pyrtl.conditional_assignment:
            with (self.lsu_op == or1200_definitions.OR1200_LSUOP_SW) | \
                (self.lsu_op == or1200_definitions.OR1200_LSUOP_SH) |  \
                self.lsu_op == or1200_definitions.OR1200_LSUOP_SB:
                #self.lsu_addrofs[11:32] |= pyrtl.concat([self.ex_insn[25]]*16, self.ex_insn[21:26])
                lsu_addrofs = [i for i in self.lsu_addrofs]
                lsu_addrofs[0:11] = self.ex_insn[0:11]
                lsu_addrofs[11:32] = pyrtl.concat_list([self.ex_insn[21:26]] + [self.ex_insn[25]]*16)
                self.lsu_addrofs |= pyrtl.concat(*reversed(lsu_addrofs))
            with pyrtl.otherwise:
                #self.lsu_addrofs[11:32] |= pyrtl.concat([self.ex_insn[15]]*16, self.ex_insn[11:16])
                lsu_addrofs = [i for i in self.lsu_addrofs]
                lsu_addrofs[0:11] = self.ex_insn[0:11]
                lsu_addrofs[11:32] = pyrtl.concat_list([self.ex_insn[11:16]] + [self.ex_insn[25]]*16)
                self.lsu_addrofs |= pyrtl.concat(*reversed(lsu_addrofs))
                
#Register file write address
class WriteAddr(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.rf_addrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.pre_branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.rf_addrw |= pyrtl.Const(0x0, bitwidth=5)
            with (~self.ex_freeze & self.id_freeze) == or1200_definitions.ONE:
                self.rf_addrw |= pyrtl.Const(0x0, bitwidth=5)
            with ~self.ex_freeze == or1200_definitions.ONE:
                with (self.pre_branch_op == or1200_definitions.OR1200_BRANCHOP_JR) | \
                (self.pre_branch_op == or1200_definitions.OR1200_BRANCHOP_BAL):
                    self.rf_addrw |= pyrtl.Const(9, bitwidth=5)
                with pyrtl.otherwise:
                    self.rf_addrw |= self.id_insn[21:26]
                    
#rf_addrw in wb stage (used in forwarding logic)
class RfInWb(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.wb_rfaddrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)
        self.rf_addrw = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_REGFILE_ADDR_WIDTH)        
        self.wb_freeze = pyrtl.WireVector(bitwidth=1)        

        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.wb_rfaddrw |= pyrtl.Const(0, bitwidth=5)
            with ~self.wb_freeze == or1200_definitions.ONE:
                self.wb_rfaddrw |= self.rf_addrw
                
#Instruction latch in id_insn
class InsnInId(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.if_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.id_insn |= pyrtl.concat(or1200_definitions.OR1200_OR32_NOP, pyrtl.Const(0x0410000, bitwidth=26))
            with self.flushpipe == or1200_definitions.ONE:
                self.id_insn |= pyrtl.concat(or1200_definitions.OR1200_OR32_NOP, pyrtl.Const(0x0410000, bitwidth=26))
            with ~self.id_freeze == or1200_definitions.ONE:
                self.id_insn |= self.if_insn
                
#Instruction latch in ex_insn
class InsnInEx(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.ex_insn = pyrtl.WireVector(bitwidth=32)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.ex_insn |= pyrtl.concat(or1200_definitions.OR1200_OR32_NOP, pyrtl.Const(0x0410000, bitwidth=26))
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.ex_insn |= pyrtl.concat(or1200_definitions.OR1200_OR32_NOP, pyrtl.Const(0x0410000, bitwidth=26))
            with ~self.ex_freeze == or1200_definitions.ONE:
                self.ex_insn |= self.id_insn
                
#Instruction latch in wb_insn
class InsnInWb(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.wb_insn = pyrtl.WireVector(bitwidth=32)
        self.ex_insn = pyrtl.WireVector(bitwidth=32)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.wb_freeze = pyrtl.WireVector(bitwidth=1)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.wb_insn |= pyrtl.concat(or1200_definitions.OR1200_OR32_NOP, pyrtl.Const(0x0410000, bitwidth=26))
            with self.flushpipe == or1200_definitions.ONE:
                self.wb_insn |= pyrtl.concat(or1200_definitions.OR1200_OR32_NOP, pyrtl.Const(0x0410000, bitwidth=26))
            with ~self.wb_freeze == or1200_definitions.ONE:
                self.wb_insn |= self.ex_insn
                
#Decode of sel_imm
class DecodeSelimm(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.sel_imm = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.if_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
            with ~self.id_freeze == or1200_definitions.ONE:
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_JALR:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_JR:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1) 
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_RFE:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_MFSPR:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_MTSPR:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_XSYNC:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_SW:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_SB:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_SH:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_ALU:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_SFXX:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_NOP:
                    self.sel_imm |= pyrtl.Const(0b0, bitwidth=1)
                with pyrtl.otherwise:
                    self.sel_imm |= pyrtl.Const(0b1, bitwidth=1)
                    
#Decode of except_illegal
class DecodeExcept(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.except_illegal = pyrtl.WireVector(bitwidth=1)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.except_illegal |= pyrtl.Const(0b0, bitwidth=1)
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.except_illegal |= pyrtl.Const(0b0, bitwidth=1)
            with ~self.ex_freeze == or1200_definitions.ONE:
                with (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_J) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_JAL) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_JALR) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_JR) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_BNF) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_BF) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_RFE) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MOVHI) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MFSPR) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_XSYNC) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LWZ) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LBZ) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LBS) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LHZ) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LHS) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDI) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDIC) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ANDI) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ORI) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_XORI) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SH_ROTI) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SFXXI) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MTSPR) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SW) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SB) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SH) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ALU) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SFXX) | \
                    (self.id_insn[26:32] == or1200_definitions.OR1200_OR32_NOP):
                        self.except_illegal |= pyrtl.Const(0b0, bitwidth=1)
            with pyrtl.otherwise:
                self.except_illegal |= pyrtl.Const(0b1, bitwidth=1)
                        
#Decode of alu_op
class DecodeOfAluop(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.alu_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.alu_op |= or1200_definitions.OR1200_ALUOP_NOP
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.alu_op |= or1200_definitions.OR1200_ALUOP_NOP
            with ~self.ex_freeze == or1200_definitions.ONE:
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_J:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_IMM
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_JAL:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_IMM
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_BNF:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_NOP
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_BF:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_NOP
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MOVHI:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_MOVHI
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MFSPR:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_MFSR
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MTSPR:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_MTSR
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDI:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_ADD
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDIC:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_ADDC
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ANDI:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_AND
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ORI:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_OR
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_XORI:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_XOR
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SH_ROTI:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_SHROT
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SFXXI:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_COMP
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ALU:
                    self.alu_op |= self.id_insn[0:4]
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SFXX:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_COMP
                with pyrtl.otherwise:
                    self.alu_op |= or1200_definitions.OR1200_ALUOP_NOP
                    
#Decode of shrot_op
class DecodeOfShrotop(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.shrot_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SHROTOP_WIDTH)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.shrot_op |= or1200_definitions.OR1200_SHROTOP_NOP
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.shrot_op |= or1200_definitions.OR1200_SHROTOP_NOP
            with ~self.ex_freeze == or1200_definitions.ONE:
                self.shrot_op |= self.id_insn[or1200_definitions.OR1200_SHROTOP_POS]
                
#Decode of rfwb_op
class DecodeOfRfwbop(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.rfwb_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_RFWBOP_WIDTH)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_NOP
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_NOP
            with ~self.ex_freeze == or1200_definitions.ONE:
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_JAL: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_LR
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_JALR: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_LR
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MOVHI: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_MFSPR: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_SPRS
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LWZ: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_LSU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LBZ: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_LSU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LBS: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_LSU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LHZ: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_LSU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LHS: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_LSU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDI: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ADDIC: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ANDI: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ORI: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_XORI: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SH_ROTI: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_ALU: 
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_ALU
                with pyrtl.otherwise:
                    self.rfwb_op |= or1200_definitions.OR1200_RFWBOP_NOP
                    
#Decode of pre_branch_op
class DecodeOfPre(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.pre_branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.if_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_NOP
            with self.flushpipe == or1200_definitions.ONE:
                self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_NOP
            with ~self.id_freeze == or1200_definitions.ONE:
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_J:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_BAL
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_JAL:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_BAL
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_JALR:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_JR
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_JR:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_JR
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_BNF:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_BNF
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_BF:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_BF
                with self.if_insn[26:32] == or1200_definitions.OR1200_OR32_RFE:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_RFE
                with pyrtl.otherwise:
                    self.pre_branch_op |= or1200_definitions.OR1200_BRANCHOP_NOP
                    
#Generation of branch_op
class GeneratOfBranch(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.pre_branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.branch_op |= or1200_definitions.OR1200_BRANCHOP_NOP
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.branch_op |= or1200_definitions.OR1200_BRANCHOP_NOP
            with ~self.ex_freeze == or1200_definitions.ONE:
                self.branch_op |= self.pre_branch_op
                
#Decode of lsu_op
class DecodeOfLsuop(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.lsu_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_LSUOP_WIDTH)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.lsu_op |= or1200_definitions.OR1200_LSUOP_NOP
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.lsu_op |= or1200_definitions.OR1200_LSUOP_NOP
            with ~self.ex_freeze == or1200_definitions.ONE:
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LWZ:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_LWZ
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LBZ:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_LBZ
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LBS:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_LBS
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LHZ:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_LHZ
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_LHS:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_LHS
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SW:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_SW
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SB:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_SB
                with self.id_insn[26:32] == or1200_definitions.OR1200_OR32_SH:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_SH
                with pyrtl.otherwise:
                    self.lsu_op |= or1200_definitions.OR1200_LSUOP_NOP
                    
#Decode of comp_op
class DecodeOfCompop(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.comp_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_COMPOP_WIDTH)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.comp_op |= pyrtl.Const(0, bitwidth=4)
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.comp_op |= pyrtl.Const(0, bitwidth=4)
            with ~self.ex_freeze == or1200_definitions.ONE:
                self.comp_op |= self.id_insn[21:25]
                
#Decode of l.sys
class DecodeOfLsys(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.sig_syscall = pyrtl.WireVector(bitwidth=1)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.sig_syscall |= pyrtl.Const(0b0, bitwidth=1)
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.sig_syscall |= pyrtl.Const(0b0, bitwidth=1)
            with ~self.ex_freeze == or1200_definitions.ONE:
                self.sig_syscall |= (self.id_insn[23:32] == pyrtl.concat(or1200_definitions.OR1200_OR32_XSYNC, pyrtl.Const(0b0, bitwidth=3)))
                
#Decode of l.trap
class DecodeOfLtrap(object):
    def __init__(self):
        #self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.sig_trap = pyrtl.WireVector(bitwidth=1)
        self.ex_freeze = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)
        self.id_insn = pyrtl.WireVector(bitwidth=32)
        self.du_hwbkpt = pyrtl.WireVector(bitwidth=1)
        
        with pyrtl.conditional_assignment:
            with self.rst == or1200_definitions.ONE:
                self.sig_trap |= pyrtl.Const(0b0, bitwidth=1)
            with (~self.ex_freeze & self.id_freeze | self.flushpipe) == or1200_definitions.ONE:
                self.sig_trap |= pyrtl.Const(0b0, bitwidth=1)
            with ~self.ex_freeze == or1200_definitions.ONE:
                self.sig_trap |= (self.id_insn[23:32] == pyrtl.concat(or1200_definitions.OR1200_OR32_XSYNC, pyrtl.Const(0b010, bitwidth=3))) | self.du_hwbkpt

if __name__ == '__main__':
    ctrl = Or1200Ctrl()
    #sim = pyrtl.GPUSim_now.GPUSim('ctrl')

    #com = pyrtl.CompiledSimulation()

    input_width = []
    from pyrtl.wire import Input

    IN = pyrtl.working_block().wirevector_subset(Input)
    for inn in IN:
        name = inn.name
        width = inn.bitwidth
        input_width.append([name, width])
    import random

    max_ = 0
    com_time = 0
    ess_time = 0
    num = 1
    for i in range(num):
        print(i)

        inputs_random = {}
        inputs_select = {}
        inputs_old = {}
        inputs_ = {}

        for inp in input_width:
            inputs_random[inp[0]] = []
            inputs_select[inp[0]] = []
            result = random.randint(0, 2 ** inp[1] - 1)
            inputs_old[inp[0]] = result

        for j in range(131072):
            for inp in input_width:
                result = random.randint(0, 2 ** inp[1] - 1)
                inputs_[inp[0]] = result
                inputs_random[inp[0]].append(result)
            if random.random() < 0.2:
                for name in inputs_old:
                    inputs_select[name].append(inputs_old[name])
            else:
                for name in inputs_:
                    inputs_select[name].append(inputs_[name])
                    inputs_old[name] = inputs_[name]
        #time1 = com.step_multiple(inputs_select)
    #sim = pyrtl.GPUSim_loopcpugpu_reg_dll.GPUSim('ctrl_reg', 64, 20)
    # sim.make_input(inputs_select)
    sim2 = pyrtl.GPUSim_now_loopcpugpu_dll.GPUSim('ctrl', 64, 20)
    sim2.make_input(inputs_select)